home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / MacPerl / MPScript.c < prev    next >
Text File  |  1993-12-12  |  15KB  |  823 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPScript.c        -    Handle scripts
  4. Author    :    Matthias Neeracher
  5. Started    :    16Aug93                                Language    :    MPW C
  6. Modified    :    17Aug93    MN    Set up correct default directory
  7.                 14Oct93    MN    Run front window
  8. Last        :    14Oct93
  9. *********************************************************************/
  10.  
  11. #include <AERegistry.h>
  12. #include <String.h>
  13. #include <TFileSpec.h>
  14. #include <setjmp.h>
  15. #include <sys/types.h>
  16. #include <ctype.h>
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. #include <Signal.h>
  21. #include <StandardFile.h>
  22. #include <Resources.h>
  23. #include <PLStringFuncs.h>
  24. #include <SysEqu.h>
  25.  
  26. #include "MPScript.h"
  27. #include "MPWindow.h"
  28. #include "MPAppleEvents.h"
  29.  
  30. int                 run_perl(int, char **, char **);
  31. void                 reenter();
  32. extern Handle    PerlReply;
  33. extern int        PerlQuit;
  34. extern char     gPseudoFileName[];
  35.  
  36. #ifndef RUNTIME
  37. pascal Boolean GetScriptFilter(ParmBlkPtr    info, void * data)
  38. {
  39. #pragma unused(data)
  40. #else
  41. pascal Boolean GetScriptFilter(ParmBlkPtr    info)
  42. {
  43. #endif
  44.     switch (info->fileParam.ioFlFndrInfo.fdType) {
  45.     case 'APPL':
  46.         switch (info->fileParam.ioFlFndrInfo.fdCreator) {
  47.         case MPRtSig:
  48.             return false;
  49.         case MPAppSig:
  50.             return !info->fileParam.ioFlLgLen;
  51.         default:
  52.             return true;
  53.         }
  54.     case 'TEXT':
  55.         return false;
  56.     default:
  57.         return true;
  58.     }
  59. }
  60.  
  61. #ifndef RUNTIME
  62.  
  63. #define gsDebugItem        10
  64.  
  65. pascal short GetScriptHook(short item, DialogPtr dlg, void * params)
  66. {
  67.     short                kind;
  68.     ControlHandle    dbg;
  69.     Rect                r;
  70.     Boolean *        par = (Boolean *) params;
  71.     
  72.     if (GetWRefCon(dlg) != 'stdf')
  73.         return item;
  74.  
  75.     switch (item) {
  76.     case sfHookFirstCall:
  77.         *par    =    false;
  78.     
  79.         return sfHookFirstCall;
  80.     case gsDebugItem:
  81.         *par = !*par;
  82.         
  83.         GetDItem(dlg, item, &kind, (Handle *) &dbg, &r);
  84.         
  85.         SetCtlValue(dbg, *par);
  86.         
  87.         return sfHookNullEvent;
  88.     default:
  89.         return item;
  90.     }
  91. }
  92.  
  93. static void SendScriptEvent(
  94.     DescType argType, 
  95.     Ptr         argPtr, 
  96.     Handle    argHdl,
  97.     Size         argSize, 
  98.     Boolean     debug)
  99. {
  100.     OSErr                    err;
  101.     AppleEvent            cmd, repl;
  102.     AEAddressDesc        addr;
  103.     
  104.     if (err = MakeSelfAddress(&addr))
  105.         goto failedAddress;
  106.         
  107.     if (err = 
  108.         AECreateAppleEvent(
  109.             kAEMiscStandards, kAEDoScript, &addr, 
  110.             kAutoGenerateReturnID, kAnyTransactionID, 
  111.             &cmd)
  112.     )
  113.         goto failedAppleEvent;
  114.     
  115.     if (argHdl) {
  116.         HLock(argHdl);
  117.         argPtr = *argHdl;
  118.     }
  119.     
  120.     if (err = AEPutParamPtr(&cmd, keyDirectObject, argType, argPtr, argSize))
  121.         goto failedParam;
  122.     
  123.     if (debug)
  124.         if (err =
  125.             AEPutParamPtr(
  126.                 &cmd, 'DEBG', 
  127.                 typeBoolean, (Ptr) &debug, sizeof(Boolean))
  128.         )
  129.             goto failedParam;
  130.         
  131.     err =
  132.         AESend(
  133.             &cmd,
  134.             &repl,
  135.             kAENoReply+kAEAlwaysInteract,
  136.             kAENormalPriority,
  137.             kAEDefaultTimeout,
  138.             nil,
  139.             nil);
  140.  
  141.     AEDisposeDesc(&repl);
  142. failedParam:    
  143.     if (argHdl)
  144.         HUnlock(argHdl);
  145.         
  146.     AEDisposeDesc(&cmd);
  147. failedAppleEvent:
  148.     AEDisposeDesc(&addr);
  149. failedAddress:
  150.     ;
  151. }
  152.  
  153. static SFTypeList    PerlFileTypes    = {'TEXT', 'APPL'};
  154.  
  155. pascal void DoScriptMenu(short theItem)
  156. {
  157.     StandardFileReply    reply;
  158.     Point                    where;
  159.     Boolean                debug;
  160.     
  161.     where.h = where.v = -1;
  162.     
  163.     switch (theItem) {
  164.     case pmRun:
  165.         CustomGetFile(
  166.             GetScriptFilter,
  167.             2,
  168.             PerlFileTypes,
  169.             &reply,
  170.             GetScriptDialog,
  171.             where,
  172.             GetScriptHook,
  173.             (ModalFilterYDProcPtr) nil,
  174.             nil,
  175.             (ActivateYDProcPtr) nil,
  176.             &debug);
  177.         if (reply.sfGood)
  178.             SendScriptEvent(typeFSS, (Ptr) &reply.sfFile, nil, sizeof(FSSpec), debug);
  179.         break;
  180.     case pmRunFront:
  181.         {
  182.             DPtr    doc = DPtrFromWindowPtr(FrontWindow());
  183.             
  184.             if (!doc || doc->kind != kDocumentWindow)
  185.                 break;
  186.             
  187.             if (doc->dirty || !doc->u.reg.everSaved) {
  188.                 if (doc->u.reg.everSaved)
  189.                     strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
  190.                 else
  191.                     getwtitle(FrontWindow(), gPseudoFileName);
  192.  
  193.                 SendScriptEvent(
  194.                     typeChar, nil, (*doc->theText)->hText, 
  195.                     GetHandleSize((*doc->theText)->hText),
  196.                     false);
  197.             } else
  198.                 SendScriptEvent(typeFSS, (Ptr) &doc->theFSSpec, nil, sizeof(FSSpec), false);
  199.         }
  200.         break;
  201.     }
  202. }
  203.  
  204. #endif
  205.  
  206. static char *        PerlArgs[]     = {
  207.     "MacPerl",
  208.     0,
  209.     0,
  210.     0,
  211.     0,
  212.     0,
  213.     0,
  214.     0,
  215.     0,
  216.     0,
  217.     0,
  218.     0,
  219.     0,
  220.     0,
  221.     0,
  222.     0,
  223.     0,
  224.     0,
  225.     0,
  226.     0,
  227.     0,
  228.     0,
  229.     0,
  230.     0,
  231.     0,
  232.     0,
  233.     0,
  234.     0
  235. };
  236.  
  237. static char *        PerlEnviron[] = {
  238.     "PERLDB=require \"macperldb.pl\"",
  239.     0,
  240.     0
  241. };
  242.  
  243. extern char * perldbgname;
  244.  
  245. pascal void InitPerlEnviron()
  246. {
  247.     char **     env = PerlEnviron;
  248.     char *    eq;
  249.     
  250.     while (*env)
  251.         if (eq = strchr(*env++, '='))
  252.             *eq = 0;
  253.     
  254.     perldbgname = "Dev:Console:Debug Log";
  255. }
  256.  
  257. char * getenv(char * var)
  258. {
  259.     char ** env;
  260.     
  261.     for (env = PerlEnviron; *env; ++env)
  262.         if (!strcmp(*env, var))
  263.             return *env + strlen(*env) + 1;
  264.     
  265.     return nil;
  266. }
  267.  
  268. static jmp_buf    ExitPerl;
  269.  
  270. void real_exit(int status);
  271.  
  272. void exit(int status)
  273. {
  274.     if (gRunningPerl)
  275.         longjmp(ExitPerl, -status);
  276.     else
  277.         real_exit(status);
  278. }
  279.  
  280. typedef void (*atexitfn)();
  281.  
  282. static atexitfn     PerlExitFn[20];
  283. static int            PerlExitCnt;
  284.  
  285. int real_atexit(atexitfn func);
  286.  
  287. int atexit(atexitfn func)
  288. {
  289.     if (gRunningPerl)
  290.         PerlExitFn[PerlExitCnt++] = func;
  291.     else
  292.         return real_atexit(func);
  293.         
  294.     return 0;
  295. }
  296.  
  297. void CleanupPerl()
  298. {
  299.     int i;
  300.     extern FILE * _lastbuf;
  301.  
  302.     UseResFile(gAppFile);
  303.  
  304.     // Borrowed from GUSI
  305.     
  306.     // Close stdio files (necessary to flush buffers)
  307.     // This implementation is not nice, but who cares ?
  308.     // In case you wonder, _iob is defined in <stdio.h>
  309.  
  310.     for (i = 0; _iob+i<_lastbuf; i++)
  311.         fflush(_iob+i);
  312.  
  313.     for (i = 0; _iob+i<_lastbuf; i++)
  314.         fclose(_iob+i);
  315.  
  316.     // Close all files
  317.  
  318.     for (i = 0; i<FD_SETSIZE; ++i)
  319.         close(i);
  320.  
  321.     while (PerlExitCnt)
  322.         PerlExitFn[--PerlExitCnt]();
  323.  
  324.     UseResFile(gAppFile);
  325.     reenter();
  326.     
  327.     open("Dev:Console", O_RDONLY);
  328.     open("Dev:Console", O_WRONLY);
  329.     open("Dev:Console", O_WRONLY);
  330.     
  331.     fopen("Dev:Console", "r");
  332.     fopen("Dev:Console", "w");
  333.     fopen("Dev:Console", "w");
  334. }
  335.  
  336. enum {
  337.     extractDone            = -4,
  338.     extractDir            = -3,
  339.     extractCpp            = -2,
  340.     extractDebug         = -1
  341. };
  342.  
  343. typedef char * (*ArgExtractor)(void * data, int index);
  344.  
  345. pascal void RunScript(ArgExtractor extractor, void * data)
  346. {
  347.     int        ArgC;
  348.     short        resFile;
  349.     Handle    libs;
  350.     Str255    lib;
  351.     char    *    res;
  352.     int        i;
  353.  
  354.     PtrToHand("PERLLIB", &libs, 8);
  355.     
  356.     resFile = CurResFile();
  357.     UseResFile(gPrefsFile);
  358.     
  359.     for (ArgC = 1; ; ++ArgC) {
  360.         GetIndString(lib, LibraryPaths, ArgC);
  361.         
  362.         if (!lib[0])
  363.             break;
  364.             
  365.         if (ArgC > 1)
  366.             PtrAndHand(",", libs, 1);
  367.         
  368.         PtrAndHand(lib+1, libs, lib[0]);
  369.     }
  370.     
  371.     UseResFile(resFile);
  372.     
  373.     if (PerlEnviron[1])
  374.         DisposePtr(PerlEnviron[1]);
  375.     
  376.     PerlEnviron[1] = NewPtr(GetHandleSize(libs)+1);
  377.     BlockMove(*libs, PerlEnviron[1], GetHandleSize(libs));
  378.     PerlEnviron[1][GetHandleSize(libs)] = 0;
  379.     DisposeHandle(libs);
  380.     
  381.     ArgC = 1;
  382.     
  383.     {
  384.         char        path[256];
  385.     
  386.         strcpy(path, extractor(data, extractDir));
  387.         chdir(path);
  388.     }
  389.     
  390.     if ((res = extractor(data, extractDebug)) && *res == 'y')
  391.         PerlArgs[ArgC++] = "-d";
  392.  
  393.     if ((res = extractor(data, extractCpp)) && *res == 'y')
  394.         PerlArgs[ArgC++] = "-P";
  395.  
  396.     if (res = extractor(data, 1)) {
  397.         if (gPerlPrefs.checkType && !gPseudoFile) 
  398.             PerlArgs[ArgC++] = "-x";
  399.         
  400.         PerlArgs[ArgC++] = res;
  401.     
  402.         for (i=2; PerlArgs[ArgC] = extractor(data, i); ++i, ++ArgC);
  403.     }
  404.     
  405.     extractor(data, extractDone);
  406.     
  407.     gRunningPerl     =  true;
  408.     PerlQuit            =    0;
  409.     ShowWindowStatus();
  410.     
  411.     signal(SIGINT, exit);
  412.     
  413.     if (!setjmp(ExitPerl))             
  414.         run_perl(ArgC, PerlArgs, PerlEnviron);
  415.     
  416.     CleanupPerl();
  417.     gRunningPerl = false;
  418.     
  419.     if (gScriptFile != gAppFile) {
  420.         CloseResFile(gScriptFile);
  421.         
  422.         gScriptFile = gAppFile;
  423.     }
  424.     
  425.     ShowWindowStatus();
  426.  
  427.     for (i=1; PerlArgs[i]; ++i)
  428.         DisposPtr(PerlArgs[i]);
  429.  
  430.     switch (PerlQuit) {
  431.     case 2:
  432. #ifdef RUNTIME
  433.     case 1:
  434. #endif
  435.         gQuitting = true;
  436.     }
  437. }
  438.  
  439. char * AEExtractor(void * data, int index)
  440. {
  441.     DescType            type;
  442.     Size                size;
  443.     Boolean            arg;
  444.     AppleEvent *     event;
  445.     FSSpec            spec;
  446.     AEKeyword        keywd;
  447.     static AEDesc    params = {'????', nil};
  448.     char *            retarg;
  449.     char *            path;
  450.     
  451.     event = (AppleEvent *) data;
  452.     
  453.     switch (index) {
  454.     case extractDone:
  455.         gRuntimeScript = nil;
  456.         
  457.         if (params.dataHandle)
  458.             AEDisposeDesc(¶ms);
  459.         
  460.         return nil;
  461.     case extractDir:
  462.         if (gRuntimeScript 
  463.         || (!params.dataHandle 
  464.             && AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
  465.         || AEGetNthPtr(
  466.                 ¶ms, 1, typeFSS, &keywd, &type, 
  467.                 (Ptr) &spec, sizeof(FSSpec), &size)
  468.         ) {
  469.             spec.vRefNum    =    gAppVol;
  470.             spec.parID        =    gAppDir;
  471.         } else {
  472.             short    res    = CurResFile();
  473.             
  474.             gScriptFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
  475.             
  476.             if (gPseudoFile    =     Get1NamedResource('TEXT', "\p!")) {
  477.                 strcpy(gPseudoFileName, FSp2FullPath(&spec));
  478.                 
  479.                 DetachResource(gPseudoFile);
  480.             }
  481.  
  482.             UseResFile(res);
  483.         } 
  484.         
  485.         FSpUp(&spec);
  486.         
  487.         return FSp2FullPath(&spec);
  488.     case extractDebug:
  489.         if (AEGetParamPtr(event, 'DEBG', typeBoolean, &type, (Ptr) &arg, 1, &size))
  490.             return nil;
  491.         else
  492.             return arg ? "y" : "n";
  493.     case extractCpp:
  494.         if (AEGetParamPtr(event, 'PREP', typeBoolean, &type, (Ptr) &arg, 1, &size))
  495.             return nil;
  496.         else
  497.             return arg ? "y" : "n";
  498.     default:
  499.         if (gRuntimeScript)
  500.             --index;
  501.         else if (index == 1 && gPseudoFile)
  502.             return "Dev:Pseudo";
  503.             
  504.         if (!index) {
  505.             gPseudoFile = gRuntimeScript;
  506.             
  507.             return "Dev:Pseudo";
  508.         }
  509.         
  510.         if (!params.dataHandle)
  511.             if (AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
  512.                 return nil;
  513.  
  514.         if (AEGetNthPtr(
  515.                 ¶ms, index, typeFSS,
  516.                 &keywd, &type, 
  517.                 (Ptr) &spec, sizeof(FSSpec), &size)
  518.         )     if (index == 1 && !gRuntimeScript) {
  519.                 AEDesc    script;
  520.                     
  521.                 if (AEGetNthDesc(¶ms, index, typeChar, &keywd, &script))
  522.                     return nil;
  523.                 
  524.                 gPseudoFile = script.dataHandle;
  525.                 
  526.                 if (!gPseudoFileName[0])
  527.                     strcpy(gPseudoFileName, "<AppleEvent>");
  528.                 
  529.                 return "Dev:Pseudo";
  530.             } else if (AEGetNthPtr(
  531.                 ¶ms, index, typeChar,
  532.                 &keywd, &type, 
  533.                 nil, 0, &size)
  534.             )
  535.                 return nil;
  536.             else {
  537.                 retarg = NewPtr(size+1);
  538.                 retarg[size] = 0;
  539.                 
  540.                 if (AEGetNthPtr(
  541.                     ¶ms, index, typeChar,
  542.                     &keywd, &type, 
  543.                     retarg, size, &size)
  544.                 ) {
  545.                     DisposPtr(retarg);
  546.                     
  547.                     return nil;
  548.                 } else
  549.                     return retarg;
  550.             }
  551.                 
  552.         path = FSp2FullPath(&spec);
  553.         retarg = NewPtr(strlen(path)+1);
  554.             
  555.         strcpy(retarg, path);
  556.             
  557.         return retarg;
  558.     }            
  559. }
  560.  
  561. char * StupidExtractor(void * data, int index)
  562. {
  563.     FSSpec    *        spec;
  564.     FSSpec            dir;
  565.     char *            retarg;
  566.     char *            path;
  567.     
  568.     spec = (FSSpec *) data;
  569.     
  570.     switch (index) {
  571.     case extractDone:
  572.     case extractDebug:
  573.     case extractCpp:
  574.         return nil;
  575.     case extractDir:
  576.         dir = *spec;
  577.         
  578.         {
  579.             short    res    = CurResFile();
  580.             
  581.             gScriptFile = HOpenResFile(dir.vRefNum, dir.parID, dir.name, fsRdPerm);
  582.             
  583.             if (gPseudoFile    =     Get1NamedResource('TEXT', "\p!")) {
  584.                 strcpy(gPseudoFileName, FSp2FullPath(spec));
  585.                 
  586.                 DetachResource(gPseudoFile);
  587.             }
  588.             
  589.             UseResFile(res);
  590.         } 
  591.         
  592.         FSpUp(&dir);
  593.         
  594.         return FSp2FullPath(&dir);
  595.     default:
  596.         if (index > 1)
  597.             return nil;
  598.  
  599.         if (gPseudoFile)
  600.             return "Dev:Pseudo";
  601.             
  602.         path = FSp2FullPath(spec);
  603.         retarg = NewPtr(strlen(path)+1);
  604.             
  605.         strcpy(retarg, path);
  606.             
  607.         return retarg;
  608.     }            
  609. }
  610.  
  611. char * YeOldeExtractor(void * data, int index)
  612. {
  613.     long        count;
  614.     char *    retarg;
  615.     char *    path;
  616.     FSSpec    spec;
  617.     AppFile    arg;
  618.     
  619.     count = (long) data;
  620.     
  621.     switch (index) {
  622.     case extractDone:
  623.         gRuntimeScript = nil;
  624.     case extractDebug:
  625.     case extractCpp:
  626.         return nil;
  627.     case extractDir:
  628.         if (gRuntimeScript) {
  629.             spec.vRefNum = gAppVol;
  630.             spec.parID   = gAppDir;
  631.         } else {
  632.             short    res    =    CurResFile();
  633.             
  634.             GetAppFiles(1, &arg);
  635.     
  636.             WD2FSSpec(arg.vRefNum, arg.fName, &spec);
  637.             
  638.             gScriptFile    =    HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
  639.             
  640.             if (gPseudoFile    =     Get1NamedResource('TEXT', "\p!")) {
  641.                 strcpy(gPseudoFileName, FSp2FullPath(&spec));
  642.                 
  643.                 DetachResource(gPseudoFile);
  644.             }
  645.             
  646.             UseResFile(res);
  647.         }
  648.         
  649.         FSpUp(&spec);
  650.         
  651.         return FSp2FullPath(&spec);
  652.     default:
  653.         if (index - (gRuntimeScript != 0) > count)
  654.             return nil;
  655.  
  656.         if (gRuntimeScript)
  657.             --index;
  658.         else if (index == 1 && gPseudoFile)
  659.             return "Dev:Pseudo";
  660.             
  661.         if (!index) {
  662.             gPseudoFile = gRuntimeScript;
  663.             
  664.             return "Dev:Pseudo";
  665.         }
  666.  
  667.         GetAppFiles(index, &arg);
  668.     
  669.         WD2FSSpec(arg.vRefNum, arg.fName, &spec);
  670.         
  671.         path = FSp2FullPath(&spec);
  672.         retarg = NewPtr(strlen(path)+1);
  673.             
  674.         strcpy(retarg, path);
  675.             
  676.         return retarg;
  677.     }            
  678. }
  679.  
  680. pascal OSErr DoScript(const AppleEvent *event, AppleEvent *reply, long refCon)
  681. {
  682. #pragma unused (refCon)
  683.  
  684.     if (gRunningPerl) {
  685.         const AppleEvent * e[2];
  686.         
  687.         e[0] = event;
  688.         e[1] = reply;
  689.         
  690.         PtrAndHand((Ptr) e, (Handle) gWaitingScripts, 8);
  691.         
  692.         return AESuspendTheCurrentEvent(event);
  693.     }
  694.     
  695.     RunScript(AEExtractor, event);
  696.     
  697.     if (PerlReply) {
  698.         HLock(PerlReply);
  699.         AEPutParamPtr(
  700.                     reply, keyDirectObject,
  701.                     typeChar, *PerlReply, GetHandleSize(PerlReply));
  702.         DisposeHandle(PerlReply);
  703.         PerlReply = nil;
  704.     }
  705.     
  706.     return noErr;
  707. }
  708.  
  709. #ifdef RUNTIME
  710.  
  711. pascal void DoScriptMenu(short theItem)
  712. {
  713.     switch (theItem) {
  714.     case pmRun:
  715.         {
  716.             Point         wh;
  717.             SFTypeList    types;
  718.             SFReply        reply;
  719.             FSSpec        spec;
  720.          
  721.             wh.h = wh.v = 75;
  722.             types[0]    = 'TEXT';
  723.             types[1]    = 'APPL';
  724.          
  725.             SFGetFile(wh, "", GetScriptFilter, 2, types, (DlgHookProcPtr) nil, &reply);
  726.         
  727.             if (reply.good) {
  728.                 WD2FSSpec(reply.vRefNum, reply.fName, &spec);
  729.                         
  730.                 RunScript(StupidExtractor, &spec);
  731.             }
  732.         }
  733.         break;
  734.     case pmRunFront:
  735.         {
  736.             DPtr    doc = DPtrFromWindowPtr(FrontWindow());
  737.             
  738.             if (!doc || doc->kind != kDocumentWindow)
  739.                 break;
  740.             
  741.             if (doc->dirty || !doc->u.reg.everSaved) {
  742.                 gRuntimeScript = (*doc->theText)->hText;
  743.                 
  744.                 HandToHand(&gRuntimeScript);
  745.                 
  746.                 if (doc->u.reg.everSaved)
  747.                     strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
  748.                 else
  749.                     getwtitle(FrontWindow(), gPseudoFileName);
  750.                 
  751.                 RunScript(YeOldeExtractor, (void *) 0);
  752.             } else
  753.                 RunScript(StupidExtractor, &doc->theFSSpec);
  754.         }
  755.         break;
  756.     }
  757. }
  758. #endif
  759.  
  760. pascal Boolean DoRuntime()
  761. {
  762.     short        message;
  763.     short        count;
  764.     FSSpec    spec;
  765.     
  766.     if (gRuntimeScript = Get1NamedResource('TEXT', "\p!")) {
  767.         spec.vRefNum     =     gAppVol;
  768.         spec.parID        =    gAppDir;
  769.         PLstrcpy(spec.name, (StringPtr) CurApName);
  770.         strcpy(gPseudoFileName, FSp2FullPath(&spec));
  771.         
  772.         DetachResource(gRuntimeScript);
  773.     }
  774.  
  775. #ifndef RUNTIME
  776.     return false;
  777. #else
  778.     if (gAppleEventsImplemented)
  779.         return false;
  780.         
  781.     CountAppFiles(&message, &count);
  782.     
  783.     if (count) {
  784.         if (message == appPrint) {
  785.             int        i;
  786.            AppFile    arg;
  787.         
  788.             for (i=0; i++<count; ) {
  789.                 GetAppFiles(i, &arg);
  790.             
  791.                 WD2FSSpec(arg.vRefNum, arg.fName, &spec);
  792.                 
  793.                 if (!IssueAEOpenDoc(spec)) {
  794.                     IssuePrintWindow(FrontWindow());
  795.                     IssueCloseCommand(FrontWindow());
  796.                 }
  797.             }
  798.             
  799.             return true;
  800.         } 
  801.     } else {
  802.         if (!gRuntimeScript) {
  803.             int        i;
  804.            AppFile    arg;
  805.         
  806.             for (i=0; i++<count; ) {
  807.                 GetAppFiles(i, &arg);
  808.             
  809.                 WD2FSSpec(arg.vRefNum, arg.fName, &spec);
  810.                 
  811.                 IssueAEOpenDoc(spec);
  812.             }
  813.             
  814.             return false;
  815.         }
  816.     }
  817.     
  818.     RunScript(YeOldeExtractor, (void *) count);
  819.     
  820.     return gQuitting;
  821. #endif
  822. }
  823.